/*
 * Created by C# Express 2008.
 * User:Krug
 * Date: 2009-7-22
 * Time: 20:56
 * 
 * 
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;

namespace Logging
{
    /// <summary>
    /// The <c>Logger</c> is a logging monitor, used to record the application's information.
    /// Genrally a looger recorder (for example <c>FileLogger</c>) works with <c>Logger</c> together, so the logged information can be displaied or saved.
    /// </summary>
    public class Logger
    {
        #region event
        /// <summary>
        /// An <c>Event</c> will be fired if a new Log are writted.
        /// </summary>
        public static event EventHandler<LogMessage> OnLogged;
        #endregion

        #region static variables and methods
        static Dictionary<String, Queue<LogMessage>> logCache = new Dictionary<string, Queue<LogMessage>>();
        static int MaxCountOfQueue = 1000;
        static void RecordLog(object parameters)
        {
            try
            {
                //prepare LogMessage
                LogThreadParam p = parameters as LogThreadParam;
                LogMessage lMsg = new LogMessage(p.Application, p.Level, p.Message);
                if (OnLogged != null)
                {
                    OnLogged(null, lMsg);
                }

                //retrive queue
                Queue<LogMessage> queue = null;
                lock (logCache)
                {
                    if (!logCache.TryGetValue(p.Application, out queue))
                    {
                        queue = new Queue<LogMessage>();
                        logCache.Add(p.Application, queue);
                    }
                }

                lock (queue)
                {
                    while (queue.Count > MaxCountOfQueue)
                    {
                        queue.Dequeue();
                    }
                    queue.Enqueue(lMsg);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message, "RecordLog");
            }
        }
        #endregion

        #region variables and properties
        string applicationName;

        #endregion

        #region constructor
        public Logger(String appName)
        {
            this.applicationName = appName;
        }
        #endregion

        #region logger methods
        public void Log(LogLevel level, String logMessage)
        {
            Thread thread = new Thread(new ParameterizedThreadStart(RecordLog));
            thread.Start(new LogThreadParam(applicationName, level, logMessage));
        }
        #endregion
    }
    class LogThreadParam
    {
        internal String Application { get; set; }
        internal LogLevel Level { get; set; }
        internal String Message { get; set; }

        internal LogThreadParam(String application, LogLevel level, String logMessage)
        {
            Application = application;
            Level = level;
            Message = logMessage;
        }
    }
}
